#include<cstdio>
#include<unistd.h>
#include<cstdlib>
#include<cstring>
#include<sys/wait.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

#define NONE_REDIR -1
#define INPUT_REDIR 0
#define OUTPUT_REDIR 1
#define APPEND_REDIR 2
int g_redir_flag=NONE_REDIR;
char* g_redir_filename =NULL;

void CheckRdir(char*command)
{
    char*begin=command;
    while(*begin)
    {
        if(*begin=='>')
        {
            if(*(begin+1)=='>')
            {
                g_redir_flag=APPEND_REDIR;
                *begin='\0';
                begin+=2;
                while(*begin==' ')++begin;
                g_redir_filename=begin;
                break;
            }
            else
            {
                g_redir_flag=OUTPUT_REDIR;
                *begin='\0';
                begin+=1;
                while(*begin==' ')++begin;
                g_redir_filename=begin;
                break;
            }
        }
        else if(*begin=='<')
        {
            g_redir_flag=INPUT_REDIR;
            *begin='\0';
            begin+=1;
            while(*begin==' ')++begin;
            g_redir_filename=begin;
            break;
        }
        else ++begin;
    }
}
int main()
{
    //保持完整的字符串
    char inbuff[1024];
    //保持打散之后的字符串
    char *argv[32];
    char g_envar[64];//保存环境变量
    while(1)
    {
        printf("Please Enter#");
        fflush(stdout);
        memset(inbuff,'\0',sizeof(inbuff));
        if(fgets(inbuff,sizeof inbuff,stdin)==NULL)
            continue;
        inbuff[strlen(inbuff)-1]='\0';

        //检查重定向符号，并记录重定向方法
        CheckRdir(inbuff);

        argv[0]=strtok(inbuff," ");
        int index=1;
        if(strcmp(argv[0],"ls")==0)argv[index++]="--color=auto";
        if(strcmp(argv[0],"ll")==0)argv[0]="ls",argv[2]="-l",argv[1]="--color=auto",index=3;
        while(argv[index++]=strtok(NULL," "));//第二次调用解析原字符串时，传入NULL
        if(strcmp(argv[0],"export")==0&&argv[1]!=NULL)
        {
            strcpy(g_envar,argv[1]);
            if(putenv(g_envar)==0)
                printf("%s export success!\n",argv[1]);
            continue;
        }
        //内建命令
        if(strcmp(argv[0],"cd")==0 && argv[1]!=NULL)
        {
            chdir(argv[1]);
            printf("cd success!\n");
            continue;
        }
        pid_t id=fork();
        if(id==0)//child
        {
            if(g_redir_flag!=NONE_REDIR)
            {
                int fd;
                switch(g_redir_flag)
                {
                    case INPUT_REDIR:
                        fd=open(g_redir_filename,O_RDONLY,0666);
                        dup2(fd,0);
                        break;
                    case OUTPUT_REDIR:
                        fd=open(g_redir_filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
                        dup2(fd,1);
                        break;
                    case APPEND_REDIR:
                        fd=open(g_redir_filename,O_WRONLY|O_CREAT|O_APPEND,0666);
                        dup2(fd,1);
                        break;
                    default:
                        break;
                }
            }
            execvp(argv[0],argv);
            exit(0);
        }
        int status=0;
        pid_t ret=waitpid(id,&status,0);
        if(ret>0)printf("exit code:%d\n",WEXITSTATUS(status));

    }
    return 0;
}
